import { Transform } from "./Transform";
import { checkPointInRectangle, invertMatrix, Point, pointAppendMatrix } from "../math";
import { GameObject } from "./GameObject";
import { System } from "./System";



export class MouseControlSystem extends System {

    onStart() {
        const canvas = document.getElementById('gameCanvas') as HTMLCanvasElement;
        canvas.addEventListener('mousedown', (e) => {
            var cam: GameObject;
            var point;

            if (cam = this.engine.getGameObject("camera")) {
                const x = cam.getBehaviour(Transform).x;
                point = new Point(e.offsetX + x, e.offsetY);
            }
            else {
                point = new Point(e.offsetX, e.offsetY)
            }



            const obj = this.getHitTestResult(point);
            this.handleOnClick(obj);
        });
    }

    getHitTestResult(point: Point) {
        const result = this.hitTestChildren(this.rootGameObject, point);
        console.log(result);
        return result;
    }

    private handleOnClick(obj: GameObject) {
        if (obj && obj.onClick) {
            obj.onClick();
        }
        dispatchParentOnClick(obj);
        function dispatchParentOnClick(obj: GameObject) {
            if (obj && obj.parent) {
                if (obj.parent.onClick) {
                    obj.parent.onClick();
                }
                dispatchParentOnClick(obj.parent);
            }

        }
    }

    hitTestChildren(gameObject: GameObject, localThisPoint: Point): GameObject | null {
        for (let i = gameObject.children.length - 1; i >= 0; i--) {
            const child = gameObject.children[i];
            const childRelativeThisLocalMatrix = child.getBehaviour(Transform).localMatrix;
            const invertChildRelativeThisLocalMatrix = invertMatrix(childRelativeThisLocalMatrix);
            const childLocalPoint = pointAppendMatrix(localThisPoint, invertChildRelativeThisLocalMatrix);
            const result = this.hitTest(child, childLocalPoint);
            if (result) {
                return result;
            }
            const result2 = this.hitTestChildren(child, childLocalPoint);
            if (result2) {
                return result2;
            }
        }
        return null;
    }

    hitTest(gameObject: GameObject, localThisPoint: Point) {
        const renderer = gameObject.renderer;
        if (renderer) {
            if (checkPointInRectangle(localThisPoint, renderer.getBounds())) {
                return gameObject;
            }
            else {
                return null;
            }
        }
    }
}
